/*=====================================================
Critical Links
Auto Configuration Server

Authors:
	Rui Eduardo Gouveia Gil - r-gil@critical-links.com

Date: 2010
Version 0.1
=======================================================*/
#include "database/DataBase.h"
#include "data/Device.h"

namespace acs
{

Device::Device() : groupID(0), configID(0), lastRestoreConfigID(0), configMode(DCM_AUTOMATIC_FIRST_CONFIG), contacted(0), lastBackup(0), lastRestore(0), localChange(0), actionPeriod("0:00 23:59")
{

}

Device::~Device()
{

}

void Device::setID(const int id)
{
	this->id = id;
}

int Device::getID() const
{
	return this->id;
}

void Device::setGroupID(const int groupID)
{
	this->groupID = groupID;
}

int Device::getGroupID() const
{
	return this->groupID;
}

void Device::setConfigID(const int configID)
{
	this->configID = configID;
}

int Device::getConfigID() const
{
	return this->configID;
}

void Device::setRestoreConfigID(const int lastRestoreConfigID)
{
	this->lastRestoreConfigID = lastRestoreConfigID;
}

int Device::getRestoreConfigID() const
{
	return this->lastRestoreConfigID;
}

void Device::setConfigMode(DeviceConfigMode configMode)
{
	this->configMode = configMode;
}

DeviceConfigMode Device::getConfigMode() const
{
	return this->configMode;
}

void Device::setStatus(DeviceStatus status)
{
	this->status = status;
}

DeviceStatus Device::getStatus() const
{
	return this->status;
}

std::string Device::getStatusStr() const
{
	time_t current;
	time(&current);

	if(this->status == DS_PENDING_VALIDATION)
		return "pending validation";
	else if(this->contacted+CPE_TIMEOUT > current)
	{
		if(this->status == DS_PENDING_CONFIRMATION)
			return "pending confirmation";
		else if(this->status == DS_PENDING_BACKUP_WITH_SOUNDS || this->status == DS_PENDING_BACKUP)
			return "pending backup";
		else if(this->status == DS_PENDING_TASKS)
			return "pending tasks";
		else if(this->status == DS_EXECUTING_BACKUP)
			return "executing backup";
		else if(this->status == DS_EXECUTING_TASKS)
			return "executing tasks";
		else
			return "online";
	}
	else
		return "offline";
}

std::string Device::getStatusIcon() const
{
	time_t current;
	time(&current);

	if(this->status == DS_PENDING_VALIDATION)
		return "<img style=\"padding-left: 2px; padding-top: 5px; height: 16px;\" src=\"images/large-yellow-sphere.ico\" alt=\"not validated\" onmouseover=\"javascript:showTooltip(this,event,'pending validation');\" onmouseout=\"javascript:hideTooltip();\"/>";
	else if(this->contacted+CPE_TIMEOUT > current)
	{
		if(this->status == DS_PENDING_CONFIRMATION)
			return "<img style=\"padding-left: 2px; padding-top: 5px; height: 16px;\" src=\"images/large-yellow-sphere.ico\" alt=\"not validated\" onmouseover=\"javascript:showTooltip(this,event,'pending confirmation');\" onmouseout=\"javascript:hideTooltip();\"/>";
		else if(this->status == DS_PENDING_BACKUP_WITH_SOUNDS && this->status == DS_PENDING_BACKUP)
			return "<img style=\"padding-left: 2px; padding-top: 5px; height: 16px;\" src=\"images/large-orange-sphere.ico\" alt=\"online\" onmouseover=\"javascript:showTooltip(this,event,'pending backup');\" onmouseout=\"javascript:hideTooltip();\"/>";
		else if(this->status == DS_PENDING_TASKS)
			return "<img style=\"padding-left: 2px; padding-top: 5px; height: 16px;\" src=\"images/large-orange-sphere.ico\" alt=\"online\" onmouseover=\"javascript:showTooltip(this,event,'pending tasks');\" onmouseout=\"javascript:hideTooltip();\"/>";
		else if(this->status == DS_EXECUTING_BACKUP)
			return "<img style=\"padding-left: 2px; padding-top: 5px; height: 16px;\" src=\"images/large-blue-sphere.ico\" alt=\"online\" onmouseover=\"javascript:showTooltip(this,event,'executing backup');\" onmouseout=\"javascript:hideTooltip();\"/>";
		else if(this->status == DS_EXECUTING_TASKS)
			return "<img style=\"padding-left: 2px; padding-top: 5px; height: 16px;\" src=\"images/large-blue-sphere.ico\" alt=\"online\" onmouseover=\"javascript:showTooltip(this,event,'executing tasks');\" onmouseout=\"javascript:hideTooltip();\"/>";
		else
			return "<img style=\"padding-left: 2px; padding-top: 5px; height: 16px;\" src=\"images/large-green-sphere.ico\" alt=\"online\" onmouseover=\"javascript:showTooltip(this,event,'online');\" onmouseout=\"javascript:hideTooltip();\"/>";
	}
	else
		return "<img style=\"padding-left: 2px; padding-top: 5px; height: 16px;\" src=\"images/large-grey-sphere.ico\" onmouseover=\"javascript:showTooltip(this,event,'offline');\" onmouseout=\"javascript:hideTooltip();\"/>";
}

DeviceStatus Device::getStatusOut() const
{
	time_t current;
	time(&current);
	if(this->status == DS_PENDING_VALIDATION)
		return this->status;
	else if(this->contacted+CPE_TIMEOUT > current)
		return this->status;
	else
		return DS_OFFLINE;
}

void Device::setCreation(const time_t creation)
{
	this->creation = creation;
}

time_t Device::getCreation() const
{
	return this->creation;
}

void Device::setUpdated(const time_t updated)
{
	this->updated = updated;
}

time_t Device::getUpdated() const
{
	return this->updated;
}

void Device::setContacted(const time_t contacted)
{
	this->contacted = contacted;
}

time_t Device::getContacted() const
{
	return this->contacted;
}

void Device::setLastBackup(const time_t lastBackup)
{
	this->lastBackup = lastBackup;
}

time_t Device::getLastBackup() const
{
	return this->lastBackup;
}

void Device::updateLastBackup()
{
	time(&this->lastBackup);
}

void Device::setLastRestore(const time_t lastRestore)
{
	this->lastRestore = lastRestore;
}

time_t Device::getLastRestore() const
{
	return this->lastRestore;
}

void Device::updateLastRestore()
{
	time(&this->lastRestore);
	this->lastRestoreConfigID = this->configID;
}

void Device::setLocalChange(const time_t localChange)
{
	this->localChange = localChange;
}

time_t Device::getLocalChange() const
{
	return this->localChange;
}

void Device::setIp(const std::string& ip)
{
	this->ip=ip;
}

std::string Device::getIp() const
{
	return this->ip;
}

void Device::setSHA(const std::string& SHA)
{
	this->SHA=SHA;
}

std::string Device::getSHA() const
{
	return this->SHA;
}

void Device::setName(const std::string& name)
{
	this->name = name;
}

std::string Device::getName() const
{
	return this->name;
}

void Device::setDescription(const std::string& description)
{
	this->description = description;
}

std::string Device::getDescription() const
{
	return this->description;
}

void Device::setActionPeriod(const std::string& actionPeriod)
{
	this->actionPeriod = actionPeriod;
}

std::string Device::getActionPeriod() const
{
	return this->actionPeriod;
}

bool Device::onActionPeriod() const
{
	if(this->actionPeriod.empty())
		return true;

	rgcpp::StringTokenizer str(this->actionPeriod, ' ');
	rgcpp::StringTokenizer begin(str.nextToken(),':');
	rgcpp::StringTokenizer end(str.nextToken(),':');

	int bhour = atoi(begin.nextToken().c_str());
	int bminute = atoi(begin.nextToken().c_str());
	int btotal = bhour*60 + bminute;

	int ehour = atoi(end.nextToken().c_str());
	int eminute = atoi(end.nextToken().c_str());
	int etotal = ehour*60 + eminute;

	if(btotal == etotal)
		return false;


    time_t current;
    time(&current);
    struct tm* currentTime = localtime(&current);
    int ctotal =  currentTime->tm_hour*60 + currentTime->tm_min;

    if(btotal < etotal)
    {
    	std::cout << "From " << btotal  << " to " << etotal <<  " ? " << ctotal << std::endl;
    	if(btotal <= ctotal && ctotal <= etotal)
    		return true;
    	else
    		return false;
    }
    else
    {
    	etotal += 24*60;
    	if(ctotal < btotal)
    		ctotal += 24*60;;

    	std::cout << "From " << btotal  << " to " << etotal <<  " ? " << ctotal << std::endl;
    	if(btotal <= ctotal && ctotal <= etotal)
    		return true;
    	else
    		return false;
    }

	return false;
}

void Device::setConfigFileName(const std::string& configFileName)
{
	this->configFileName = configFileName;
}

std::string Device::getConfigFileName() const
{
	return this->configFileName;
}

void Device::setCommands(const std::vector<Command>& commands)
{
	this->commands = commands;
}

std::vector<Command> Device::getCommands() const
{
	return this->commands;
}

void Device::setBuild(const std::string& build)
{
	this->build = build;
}

std::string Device::getBuild() const
{
	return this->build;
}

void Device::setUpTime(const std::string& upTime)
{
	this->upTime = upTime;
}

std::string Device::getUpTime() const
{
	return this->upTime;
}

void Device::setRelease(const std::string& release)
{
	this->release = release;
}

std::string Device::getRelease() const
{
	return this->release;
}

void Device::setSwapUsed(const std::string& swapUsed)
{
	this->swapUsed = swapUsed;
}

std::string Device::getSwapUsed() const
{
	return this->swapUsed;
}

void Device::setMaxUsers(const std::string& maxUsers)
{
	this->maxUsers = maxUsers;
}

std::string Device::getMaxUsers() const
{
	return this->maxUsers;
}

void Device::setLicenseID(const std::string& licenseID)
{
	this->licenseID = licenseID;
}

std::string Device::getLicenseID() const
{
	return this->licenseID;
}

void Device::setSystemLoad(const std::string& systemLoad)
{
	this->systemLoad = systemLoad;
}

std::string Device::getSystemLoad() const
{
	return this->systemLoad;
}

void Device::setGuiVersion(const std::string& guiVersion)
{
	this->guiVersion = guiVersion;
}

std::string Device::getGuiVersion() const
{
	return this->guiVersion;
}

void Device::setFreeMemory(const std::string& freeMemory)
{
	this->freeMemory = freeMemory;
}

std::string Device::getFreeMemory() const
{
	return this->freeMemory;
}

void Device::setPepsVersion(const std::string& pepsVersion)
{
	this->pepsVersion = pepsVersion;
}

std::string Device::getPepsVersion() const
{
	return this->pepsVersion;
}

void Device::setCustomerName(const std::string& customerName)
{
	this->customerName = customerName;
}

std::string Device::getCustomerName() const
{
	return this->customerName;
}

void Device::setPartitionVar(const std::string& partitionVar)
{
	this->partitionVar = partitionVar;
}

std::string Device::getPartitionVar() const
{
	return this->partitionVar;
}

void Device::setPartitionRoot(const std::string& partitionRoot)
{
	this->partitionRoot = partitionRoot;
}

std::string Device::getPartitionRoot() const
{
	return this->partitionRoot;
}

void Device::setPartitionHome(const std::string& partitionHome)
{
	this->partitionHome = partitionHome;
}

std::string Device::getPartitionHome() const
{
	return this->partitionHome;
}

void Device::setInstalledMemory(const std::string& installedMemory)
{
	this->installedMemory = installedMemory;
}

std::string Device::getInstalledMemory() const
{
	return this->installedMemory;
}

void Device::setHardwareDescription(const std::string& hardwareDescription)
{
	this->hardwareDescription = hardwareDescription;
}

std::string Device::getHardwareDescription() const
{
	return this->hardwareDescription;
}

std::string Device::toXML() const
{
	std::stringstream stream;

	stream << "<Device>";
	stream << "<ID>" <<  this->id << "</ID>";
	stream << "<GroupID>" <<  this->groupID << "</GroupID>";
	stream << "<ConfigID>" <<  this->configID << "</ConfigID>";
	stream << "<ConfigMode>" <<  this->configMode << "</ConfigMode>";
	stream << "<GroupName>" <<  DataBase::getInstance()->getGroup(this->groupID).getName() << "</GroupName>";
	stream << "<ConfigName>" <<  DataBase::getInstance()->getConfiguration(this->configID).getName() << "</ConfigName>";
	stream << "<Status>" <<  this->getStatusOut() << "</Status>";
	stream << "<StatusStr>" <<  this->getStatusStr() << "</StatusStr>";
	stream << "<StatusIcon>" <<  this->getStatusIcon() << "</StatusIcon>";
	stream << "<Updated>" <<  this->updated << "</Updated>";
	stream << "<Creation>" <<  this->creation << "</Creation>";
	stream << "<Contacted>" <<  this->contacted << "</Contacted>";
	stream << "<UpdatedStr>" <<  rgcpp::ToString(this->updated,"%Y-%m-%d %X") << "</UpdatedStr>";
	stream << "<CreationStr>" <<  rgcpp::ToString(this->creation,"%Y-%m-%d %X") << "</CreationStr>";
	stream << "<ContactedStr>" <<  ((this->contacted == 0) ? "never" : rgcpp::ToString(this->contacted,"%Y-%m-%d %X")) << "</ContactedStr>";
	stream << "<Ip>" <<  this->ip << "</Ip>";
	stream << "<Name>" <<  this->name << "</Name>";
	stream << "<Description>" <<  this->description << "</Description>";
	stream << "<ActionPeriod>" <<  this->actionPeriod << "</ActionPeriod>";
	stream << "<Release>" <<  this->release << "</Release>";
	stream << "<LicenseID>" <<  this->licenseID << "</LicenseID>";
	stream << "<CustomerName>" <<  this->customerName << "</CustomerName>";
	stream << "</Device>";

	return stream.str();
}

std::string Device::toXMLFull() const
{
	std::stringstream stream;

	stream << "<Device>";
	stream << "<ID>" <<  this->id << "</ID>";
	stream << "<GroupID>" <<  this->groupID << "</GroupID>";
	stream << "<ConfigID>" <<  this->configID << "</ConfigID>";
	stream << "<ConfigMode>" <<  this->configMode << "</ConfigMode>";
	stream << "<GroupName>" <<  DataBase::getInstance()->getGroup(this->groupID).getName() << "</GroupName>";
	stream << "<ConfigName>" <<  DataBase::getInstance()->getConfiguration(this->configID).getName() << "</ConfigName>";
	stream << "<Status>" <<  this->getStatusOut() << "</Status>";
	stream << "<StatusStr>" <<  this->getStatusStr() << "</StatusStr>";
	stream << "<StatusIcon>" <<  this->getStatusIcon() << "</StatusIcon>";
	stream << "<Updated>" <<  this->updated << "</Updated>";
	stream << "<Creation>" <<  this->creation << "</Creation>";
	stream << "<Contacted>" <<  this->contacted << "</Contacted>";
	stream << "<UpdatedStr>" <<  rgcpp::ToString(this->updated,"%Y-%m-%d %X") << "</UpdatedStr>";
	stream << "<CreationStr>" <<  rgcpp::ToString(this->creation,"%Y-%m-%d %X") << "</CreationStr>";
	stream << "<ContactedStr>" <<  ((this->contacted == 0) ? "never" : rgcpp::ToString(this->contacted,"%Y-%m-%d %X")) << "</ContactedStr>";
	stream << "<Ip>" <<  this->ip << "</Ip>";
	stream << "<Name>" <<  this->name << "</Name>";
	stream << "<Description>" <<  this->description << "</Description>";
	stream << "<ActionPeriod>" <<  this->actionPeriod << "</ActionPeriod>";
	stream << "<Release>" <<  this->release << "</Release>";
	stream << "<LicenseID>" <<  this->licenseID << "</LicenseID>";
	stream << "<CustomerName>" <<  this->customerName << "</CustomerName>";

	stream << "<RestoreConfigID>" <<  this->lastRestoreConfigID << "</RestoreConfigID>";
	if(DataBase::getInstance()->existsConfiguration(this->lastRestoreConfigID))
		stream << "<RestoreConfigName>" <<  DataBase::getInstance()->getConfiguration(this->lastRestoreConfigID).getName() << "</RestoreConfigName>";
	else
		stream << "<RestoreConfigName>Not Found</RestoreConfigName>";
	stream << "<LastBackup>" <<  this->lastBackup << "</LastBackup>";
	stream << "<LastRestore>" <<  this->lastRestore << "</LastRestore>";
	stream << "<LastBackupStr>" <<  rgcpp::ToString(this->lastBackup,"%Y-%m-%d %X") << "</LastBackupStr>";
	stream << "<LastRestoreStr>" <<  rgcpp::ToString(this->lastRestore,"%Y-%m-%d %X") << "</LastRestoreStr>";

	stream << "<Build>" <<  this->build << "</Build>";
	stream << "<UpTime>" <<  this->upTime << "</UpTime>";
	stream << "<SwapUsed>" <<  this->swapUsed << "</SwapUsed>";
	stream << "<MaxUsers>" <<  this->maxUsers << "</MaxUsers>";
	stream << "<SystemLoad>" <<  this->systemLoad << "</SystemLoad>";
	stream << "<GuiVersion>" <<  this->guiVersion << "</GuiVersion>";
	stream << "<FreeMemory>" <<  this->freeMemory << "</FreeMemory>";
	stream << "<PepsVersion>" <<  this->pepsVersion << "</PepsVersion>";
	stream << "<PartitionVar>" <<  this->partitionVar << "</PartitionVar>";
	stream << "<PartitionRoot>" <<  this->partitionRoot << "</PartitionRoot>";
	stream << "<PartitionHome>" <<  this->partitionHome << "</PartitionHome>";
	stream << "<InstalledMemory>" <<  this->installedMemory << "</InstalledMemory>";
	stream << "<HardwareDescription>" <<  this->hardwareDescription << "</HardwareDescription>";
	stream << "</Device>";

	return stream.str();
}

}
